#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <gtk/gtk.h>
/* Ajout BP 20041109 : nécessaire pour travailler sur Entry. */
#include <gtk/gtkeditable.h>

#include "callbacks.h"
#include "interface.h"
#include "support.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "calculs.h"

#define MSG_TRACE 1
void
bla_bla (int flag, const char *msg)
{
  switch (flag)
    {
    case MSG_TRACE:
      (void) fprintf (stdout, "%s %s\n", "Passé dans", msg);
      break;
    default:
      (void) fprintf (stdout, "%s\n", msg);
    }
}

gboolean
on_moins_JDA_button_press_event (GtkWidget * widget,
				 GdkEventButton * event, gpointer user_data)
{
  /* version C99 */
  bla_bla (MSG_TRACE, __func__);
  /* version gcc */
  bla_bla (MSG_TRACE, __FUNCTION__);
  return TRUE;
  /* return FALSE; */
}


gboolean
on_plus_JDA_button_press_event (GtkWidget * widget,
				GdkEventButton * event, gpointer user_data)
{

  bla_bla (MSG_TRACE, __func__);
  return FALSE;
}


void
on_fenetreTop_destroy (GtkObject * object, gpointer user_data)
{

  bla_bla (MSG_TRACE, __func__);
  gtk_main_quit ();
}



gboolean
on_moins_JDA_event (GtkWidget * widget, GdkEvent * event, gpointer user_data)
{

  bla_bla (MSG_TRACE, __func__);
  return FALSE;
}

/**
 *
 */
void
calendar_to_entry (GtkCalendar * calendar)
{
  GtkWidget *saisie_JDA = NULL;
  gchar chaine_JDA[4];
  guint year, month, day;
  /* anti infinite recursion */
  static int travail_en_cours = 0;

  bla_bla (MSG_TRACE, __func__);

  if (1 == travail_en_cours)
    return;

  /* Partons à la recherche du widget de saisie du JDA */
  saisie_JDA = lookup_widget (GTK_WIDGET (calendar), "saisie_JDA");
  if (saisie_JDA == NULL)
    {
      fprintf (stdout, "%s %s\n", "saisie_JDA",
	       "PAS TROUVÉ par lookup_widget");
    }
  else
    {
      fprintf (stdout, "%s %s\n", "saisie_JDA", "trouvé par lookup_widget");
      /* On récupère la date courante du calendrier */
      gtk_calendar_get_date (calendar, &year, &month, &day);
      fprintf (stdout, "%s %u-%u-%u\n", "la date sélectionnée est ",
	       year, month, day);
      /* Le gtk_calendar travaille sur des u_int, et avec un
       * mois dans l'intervalle [0-11] */
      sprintf ((char *) chaine_JDA, "%d",
	       date_to_JDA ((int) year, (int) month + 1, (int) day));
      fprintf (stdout, "%s|%s|%s\n", "on va mettre ", chaine_JDA,
	       " dans entry");

      travail_en_cours = 1;
      gtk_entry_set_text (GTK_ENTRY (saisie_JDA), chaine_JDA);
      travail_en_cours = 0;
      /* Et c'est fini... */
    }
}

void
on_calendar1_realize (GtkWidget * widget, gpointer user_data)
{
  bla_bla (MSG_TRACE, __func__);
  /* A priori,le widget qu'on reçoit est un calendar, donc on peut caster */
  calendar_to_entry ((GtkCalendar *) widget);
}


void
on_calendar1_day_selected (GtkCalendar * calendar, gpointer user_data)
{
  bla_bla (MSG_TRACE, __func__);
  calendar_to_entry (calendar);
}

gboolean
on_fenetreTop_delete_event (GtkWidget * widget,
			    GdkEvent * event, gpointer user_data)
{

  bla_bla (MSG_TRACE, __func__);
  /* Truc de base de Gtk : on retourne TRUE/FALSE selon que l'on */
  /* souhaite continuer ou pas (cas typique : pop_up "Vraiment quitter ?" */
  /* Dans notre cas, on quitte sans vergogne. */
  /* Le Callback "destroy" sera appelé à la suite.  */
  return FALSE;
}

/**
 *
 */
void
JDA_to_calendar (int JDA, GtkCalendar * calendar)
/* On suppose que JDA est correct (>0 et <=nb_jour_de_l'annee) */
{
  guint jour_a, mois_a, annee_a;
  guint jour_n, mois_n;
  gboolean flag_ret;
  /* Flag anti récursion infinie :
   * On va modifier le calendar, qui va appeler ses callbacks à cette occasion
   * lesquels vont modifier l'entry, et on va se retrouver ici-même.
   * */
  static int travail_en_cours = 0;

  bla_bla (MSG_TRACE, __func__);

  if (1 == travail_en_cours)
    return;

  /* Faut commencer par récupérer annee_a dans calendar !!!! */
  gtk_calendar_get_date (calendar, &annee_a, &mois_a, &jour_a);

  JDA_to_date (JDA, &annee_a, &mois_n, &jour_n);

  if (mois_n <= 0)
    {
      fprintf (stdout, "JDA_to_date a foiré : mois<=0 %d\n", mois_n);
    }
  if (mois_n > 12)
    {
      fprintf (stdout, "JDA_to_date a foiré : mois> 12%d\n", mois_n);
      mois_n = 11;
    }

  /* JDA_to_date() renvoie des mois "normaux", mais
   * gtk_calendar travaille de 0 à 11 */
  if (mois_n != 0)
    mois_n--;

  travail_en_cours = 1;

  if (mois_n != mois_a)
    {
      flag_ret = gtk_calendar_select_month (calendar, mois_n, annee_a);
      fprintf (stdout, "%s %u-%u\n", "On va régler an/mois :", annee_a,
	       mois_n);
    }
  if (jour_n != jour_a)
    fprintf (stdout, "%s %u\n", "On va régler jour :", jour_n);
  {
    gtk_calendar_select_day (calendar, jour_n);
  }
  travail_en_cours = 0;
  return;
}

int
ote_non_digit (gchar * chaine)
{
  gchar *cp1, *cp2;
  int modif = 0;

  cp1 = chaine;
  cp2 = chaine;

  while (*cp1 != 0)
    {
      if (isdigit (*cp1))
	{
	  /* On recopie et avance le pointeur de recopie */
	  *cp2 = *cp1;
	  cp2++;
	}
      else
	{
	  modif += 1;
	}
      cp1++;
    }
  return modif;
}


/** Callback appelé lorsque le champ texte "JDA" est modifié
 */
void
on_saisie_JDA_changed (GtkEditable * editable, gpointer user_data)
{
  gchar *chaine_saisie = NULL;
  GtkCalendar *calendar = NULL;
  guint annee_a;
  guint jour_n, mois_n;
  int JDA;

  bla_bla (MSG_TRACE, __func__);

  /* Méthode  :
   * 1) Check_entry_valide */

  /* Vu que le callback a reçu un "editable", on appelle
   * gtk_editable_get. On pourrait aussi utiliser gtk_entry_get_tex.
   */
  chaine_saisie = gtk_editable_get_chars (editable, 0, 10);
  /* Question  : et le free (chaine_saisie), c'est quand ? */
  if (chaine_saisie == NULL)
    {
      fprintf (stdout, "%s %s\n", "gtk_editable_get_chars",
	       "PAS RÉCUPÉRÉ chaine_saisie");
      return;
    }
  fprintf (stdout, "%s %s\n", "gtk_editable_get_chars", chaine_saisie);
  /* Surtout, ne rien faire si chaîne vide ! */
  if (0 == strlen (chaine_saisie))
    return;

  /* On ne veut QUE DES CHIFFRES ! */
  if (ote_non_digit (chaine_saisie) != 0)
    {
      gtk_entry_set_text (GTK_ENTRY (editable), chaine_saisie);
      return;
    }
  JDA = atoi (chaine_saisie);

  /* recup_info_calendar("calendar1") */
  calendar =
    GTK_CALENDAR (lookup_widget (GTK_WIDGET (editable), "calendar1"));
  if (calendar == NULL)
    {
      fprintf (stdout, "%s %s\n", "calendar1",
	       "PAS TROUVÉ par lookup_widget");
      return;
    }
  /* On récupère la date courante du calendrier */
  gtk_calendar_get_date (calendar, &annee_a, NULL, NULL);
  /* On veut UNE VALEUR PLAUSIBLE ! */
  if (JDA > nb_jour_annee (annee_a))
    {
      /* saisie trop grande. 
       * Soit on tronque a nb_jour max, soit on remet au précédent.
       * Code pour tronquer : 
       * sprintf ((char *) chaine_JDA, "%d", nb_jour_annee(annee_a));
       * gtk_entry_set_text (GTK_ENTRY (editable), chaine_JDA);
       * Code pour remettre au précédent, à partir de calendar 
       * calendar_to_entry (calendar); */
      calendar_to_entry (calendar);
      return;
    }
  if (JDA <= 0)
    {
      calendar_to_entry (calendar);
    }

  /* 2) si OK, JDA_to_calendar */
  JDA_to_calendar (JDA, calendar);

}


void
on_saisie_JDA_editing_done (GtkCellEditable * celleditable,
			    gpointer user_data)
{

  bla_bla (MSG_TRACE, __func__);

}


void
on_plus_JDA_notify (GObject * gobject, GParamSpec * arg1, gpointer user_data)
{

  bla_bla (MSG_TRACE, __func__);

}

gboolean
varie_JDA (GtkWidget * widget, int variation)
{
  const gchar *chaine_JDA = NULL;
  gchar new_chaine_JDA[4];
  static GtkWidget *saisie_JDA = NULL;
  int JDA, new_JDA;
  static GtkCalendar *calendar = NULL;
  guint jour_a, mois_a, annee_a;


  /* Partons à la recherche du widget de saisie du JDA. 
   * (Celui qu'on reçoit en argument, c'est l'eventBox, (ou peut-être
   * la flèche), mais pas le widget de saisie qui nous interesse).
   */
  if (saisie_JDA == NULL)
    {
      saisie_JDA = lookup_widget (widget, "saisie_JDA");
      if (saisie_JDA == NULL)
	{
	  fprintf (stdout, "%s %s\n", "saisie_JDA",
		   "PAS TROUVÉ par lookup_widget");
	  return FALSE;
	}
    }
  /* idem  pour le calendar */
  if (calendar == NULL)
    {
      calendar =
	GTK_CALENDAR (lookup_widget (GTK_WIDGET (widget), "calendar1"));
      if (calendar == NULL)
	{
	  fprintf (stderr, "%s %s\n", "calendar1",
		   "PAS TROUVÉ par lookup_widget");
	  return FALSE;
	}
    }

  chaine_JDA = gtk_entry_get_text (GTK_ENTRY (saisie_JDA));
  /* Question : et le free (chaine_JDA), c'est quand ? */
  /* probablement à la mort du widget. */
  if (chaine_JDA == NULL)
    {
      fprintf (stdout, "%s %s\n", "gtk_entry_get_text",
	       "PAS RÉCUPÉRÉ chaine_JDA");
      return FALSE;
    }

  gtk_calendar_get_date (calendar, &annee_a, NULL, NULL);
  JDA = atoi (chaine_JDA);
  /* Si JDA est déjà hors-limite, on ne fait rien. */
  if ((JDA < 0) || (JDA > nb_jour_annee (annee_a)))
    return FALSE;

  new_JDA = JDA + variation;
  fprintf (stderr, "new_JDA=%d\n", new_JDA);
  if (new_JDA <= 0)
    {
      /* Changement vers l'année précédentes... */
      /* Comme dans on_saisie_JDA_changed () 
       * récupérer valeur an, faire an--, ...*/
      /* On récupère la date courante du calendrier */
      gtk_calendar_get_date (calendar, &annee_a, &mois_a, &jour_a);
      annee_a--;
      mois_a = 11;		/* mois de 0 à 11 */
      new_JDA = nb_jour_annee (annee_a);
      gtk_calendar_select_month (calendar, mois_a, annee_a);
      gtk_calendar_select_day (calendar, 31);
    }
  else if (new_JDA > nb_jour_annee (annee_a))
    {
      /* TODO ; penser à changer d'année... */
      return FALSE;
    }

  sprintf ((char *) new_chaine_JDA, "%d", new_JDA);
  gtk_entry_set_text (GTK_ENTRY (saisie_JDA), new_chaine_JDA);

  return FALSE;

}

gboolean
on_event_moins_JDA_button_press_event (GtkWidget * widget,
				       GdkEventButton * event,
				       gpointer user_data)
{

  bla_bla (MSG_TRACE, __func__);
  return varie_JDA (widget, -1);
}


gboolean
on_event_plus_JDA_button_press_event (GtkWidget * widget,
				      GdkEventButton * event,
				      gpointer user_data)
{

  bla_bla (MSG_TRACE, __func__);
  return varie_JDA (widget, +1);
}
